feat: rework tool calling#753
Conversation
Coverage Report •
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7c7a0aa. Configure here.
olbychos
left a comment
There was a problem hiding this comment.
Overall looks solid. Let’s consider better patterns and rely on tests plus Anthropic/Bedrock and other provider checks.
| self._strip_nulls_for_fields(tool.input_schema.model_fields, action_input) | ||
| return action_input | ||
|
|
||
| def _strip_nulls_for_fields(self, fields: Mapping[str, Any], data: Any) -> None: |
There was a problem hiding this comment.
let clean/rework 'matreshka' code
|
|
||
| try: | ||
| native_parallel = self.parallel_tool_calls_enabled and self.inference_mode == InferenceMode.FUNCTION_CALLING | ||
| # In FUNCTION_CALLING mode with tools present, force a tool call so |
There was a problem hiding this comment.
because this is purpose of function calling inference mode for agent. Otherwise it may not call a tool, and there is no point of such iteration then.
|
|
||
| # JSON Schema keywords Anthropic's strict-mode compiler rejects. Strip them | ||
| # before sending; keep semantics in the description. | ||
| _ANTHROPIC_STRICT_UNSUPPORTED_KEYWORDS = frozenset( |
There was a problem hiding this comment.
Is there official source ? looks bad
| default=None, | ||
| description="Configuration for fallback behavior including the fallback LLM.", | ||
| ) | ||
| strict_tools: bool | list[str] = Field( |
There was a problem hiding this comment.
We have bias towards openai and anthropic/ then how about bedrock and anthropic models? gemini models? grok, etc?
| in_string = False | ||
| escape = False | ||
|
|
||
| for ch in raw: |
There was a problem hiding this comment.
Same 'matreshka' processing; maybe reconsider utils
or reuse
from pydantic_core import from_json
def parse_partial_json(raw: str):
return from_json(raw, allow_partial=True)
or
from partial_json_parser import ensure_json
def repair_truncated_json(raw: str) -> str:
return ensure_json(raw)
| must recurse into the sub-model and parse it back -- otherwise the string survives | ||
| and the nested model's Pydantic validation rejects it. | ||
| """ | ||
| from typing import Any, ClassVar, Literal |

Note
High Risk
Changes core agent LLM invocation, tool schema shaping, and parsing across OpenAI/Anthropic/LiteLLM; regressions could break tool calls, streaming, or provider compatibility.
Overview
This PR reworks function-calling and strict tool schemas end-to-end: generation is simplified (no global
stricton agent schemas), while OpenAI and Anthropic LLM nodes optionally apply provider-specific strict transforms via newstrict_toolsonBaseLLM, invoked from completion param building.Agent parsing now normalizes model output before tool validation:
_coerce_json_fields(including nested models) turns JSON-string dict fields back into objects;_strip_protocol_nullsdropsnullfor non-nullable fields so OpenAI strict “use default” semantics match Pydantic. Truncated tool arguments userepair_truncated_json. In function-calling mode with tools,tool_choice: requiredis set when the caller did not override it.Anthropic adds strict schema cleaning, a 20-tool cap, and a LiteLLM monkey-patch to forward
strict. Streaming emit helpers return completion booleans; integration tests guard answer text vsaction_inputwrappers and compare streamed tool input with null keys pruned. XML ReAct instructions tighten single-turn behavior. Tests cover nested dict coercion and richer tool schemas.Reviewed by Cursor Bugbot for commit 02f9b48. Bugbot is set up for automated code reviews on this repo. Configure here.